/**
 * @file match.h
 * @author septem (jsm920@outlook.com)
 * @brief 在win32下实现与 linux 下 glob相同的功能，具体查看man 7 glob 或 man 3 glob
 * @note 通配符匹配 globbing pathnames(用于匹配路径)
 *  1. 基本语法
 *      * 通配符 ? 匹配一个字符，不包含 /
 *      * 通配符 * 匹配0个或多个字符，不包含 /
 *      * 通配符 [abc] 匹配方括号内的字符
 *      * 通配符 [a-z] 匹配方括号内的范围字符
 *      * 通配符 [^abc] 或 [!abc] 匹配非方括号内的字符
 *      * 通配符 [^a-z] 或 [!a-z] 匹配非方括号内的范围字符
 *  2. 扩展语法
 *      * 通配符 {a,b,c} Brace Expansion，展开花括号内容，支持展开嵌套括号,例：{a,b,c}.jpg 表示 a.jpg,b.jpg,c.jpg
 *      * 通配符 ** globstar，匹配所有文件和任意层目录，如果**后面紧接着/则只匹配目录，不含隐藏目录
 *      * 通配符 ?(pattern-list) 匹配0次或1次给定的模式 
 *      * 通配符 *(pattern-list) 匹配0次或多次给定的模式
 *      * 通配符 +(pattern-list) 匹配1次或多次给定的模式
 *      * 通配符 @(pattern-list) 匹配给定的模式 
 *      * 通配符 !(pattern-list) 匹配非给定的模式
 *   pattern-list 是一组以|作为分隔符的模式集合，例如abc|a?c|ac*
 * @version 0.1
 * @date 2025-02-13
 * 
 * @copyright Copyright (c) 2025
 * 
 */
#ifndef _HEAD_GLOB_
#define _HEAD_GLOB_
#if defined(_WIN32) && defined(_MSC_VER)
// #pragma execution_character_set("utf-8")
#define WIN32_LEAN_AND_MEAN // 预处理器宏定义，它告诉编译器仅包含Windows SDK中最常用的函数和数据类型，从而减小编译时间和生成的可执行文件大小。
#include <stdio.h>
#elif defined(__linux__)
#include <stdio.h>
#endif

#ifndef roundup
#if defined(_WIN32) && defined(_MSC_VER)
//对 x 向上取 y 的整数倍
#define  roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y))
#elif defined(__linux__)
//对 x 向上取 y 的整数倍
#define  roundup(x, y) 			    \
({							        \
	typeof(y) __y = y;				\
	(((x) + (__y - 1)) / __y) * __y;\
})
#endif
#endif

enum gmatchtype_e
{
    GMATCH = 1, //确定的字符串
    GMATCH_QUESTION , //仅匹配一个任意字符 a?c.jpg => abc.jpg adc.jpg ...
    GMATCH_STAR, //匹配0个或多个字符  a*c.jpg => abc.jpg adc.jpg abdc.jpg adbc.jpg ...
    GMATCH_BRACKET, // 匹配方括号中的字符 a[bc]c.jpg => abc.jpg acc.jpg
    GMATCH_BRACKET_RANGE, // 匹配方括号中的范围字符 a[a-z]c.jpg => aac.jpg abc.jpg acc.jpg adc.jpg ...
    GMATCH_BRACKET_NEG, // 匹配非方括号中的字符 a[^bc]c.jpg a[!bc]c.jpg => aec.jpg axc.jpg ...
    GMATCH_BRACKET_RANGE_NEG, // 匹配非方括号中的范围字符 a[^a-z]c.jpg a[!a-z]c.jpg => aAc.jpg a0c.jpg ...
    GMATCH_BRACE, // 匹配花括号中的列表 a[^a-z]c.jpg a[!a-z]c.jpg => aAc.jpg a0c.jpg ...
    GMATCH_GLOBSTAR,//globstar，匹配所有文件和任意层目录，如果**后面紧接着/则只匹配目录，不含隐藏目录
    GMATCH_PATTERN_LIST_QUESTION, // ?(pattern-list) 匹配0次或1次给定的模式
    GMATCH_PATTERN_LIST_STAR, // *(pattern-list) 匹配0次或多次给定的模式
    GMATCH_PATTERN_LIST_PLUS, // +(pattern-list) 匹配1次或多次给定的模式
    GMATCH_PATTERN_LIST_AT, // @(pattern-list) 匹配给定的模式
    GMATCH_PATTERN_LIST_EXCL, // !(pattern-list) 匹配非给定的模式
};

/**
 * @brief 匹配语法
 * 
 */
typedef struct gmatchgrammar_t
{
    char type; // 匹配类型
    union _gmatch_u
    {
        struct _question_t //问号匹配
        {
            char cnt; // 问号数量
        }question; //问号匹配
        
    }d;
    
}gmatchgrammar_t;

/**
 * @brief glob 模式匹配,为防止与linux c 下的 glob 混淆,改用 gmatch_t 详见 man 3 glob 或 man 7 glob
 * 
 */
typedef struct gmatch_t
{
    int cnt;
    gmatchgrammar_t** pgg;
}gmatch_t;

/**
 * @brief 申请并初始化一个 gmatch_t
 * 
 * @param pattern 匹配模式字符串
 * @return gmatch_t* 
 */
gmatch_t* GmatchInit(char* pattern);
/**
 * @brief 注销一个gmatch_t* 
 * 
 * @param pg 
 */
void GmatchUninit(gmatch_t* pg);
/**
 * @brief 对一个 路径 path 使用 gmatch_t* pg, 返回是否匹配,是返回1,否返回0
 * 
 * @param pg 
 * @param path 
 * @return int 
 */
int Gmatch(gmatch_t* pg,char* path);
int Gmatch1(char* pattern,char* path);
int GmatchCopy(gmatch_t* src,gmatch_t* dst, unsigned int sz);
#endif // end of define _HEAD_GLOB_
